<template>
    <div class="expandable-text-container">
        <div
            ref="textRef"
            class="text-content"
            :class="{ 'overflow-hidden': isOverflowing, expanded: isExpanded }"
            :style="contentStyle"
        >
            {{ displayText }}
        </div>

        <div v-if="isOverflowing" class="toggle-button" @click="toggleExpanded">
            <span>{{ isExpanded ? collapseText : expandText }}</span>
            <i :class="iconClass"></i>
        </div>
    </div>
</template>

<script setup>
import { ref, computed, onMounted, nextTick } from 'vue';

const props = defineProps({
    text: {
        type: String,
        required: true,
    },
    rows: {
        type: Number,
        default: 3,
    },
    expandText: {
        type: String,
        default: '展开',
    },
    collapseText: {
        type: String,
        default: '收起',
    },
    animation: {
        type: Boolean,
        default: true,
    },
    animationDuration: {
        type: Number,
        default: 300,
    },
    lineHeight: {
        type: String,
        default: '1.5',
    },
});

const emit = defineEmits(['expanded', 'collapsed']);

const textRef = ref(null);
const isExpanded = ref(false);
const isOverflowing = ref(false);
const contentHeight = ref(0);
const maxHeight = ref(0);

// 计算样式
const contentStyle = computed(() => {
    const styles = {
        lineHeight: props.lineHeight,
    };

    if (props.animation && isExpanded.value) {
        styles.transition = `max-height ${props.animationDuration}ms ease`;
        styles.maxHeight = `${contentHeight.value}px`;
    } else if (props.animation && !isExpanded.value && isOverflowing.value) {
        styles.transition = `max-height ${props.animationDuration}ms ease`;
        styles.maxHeight = `${maxHeight.value}px`;
    } else if (!isExpanded.value && isOverflowing.value) {
        styles.maxHeight = `${maxHeight.value}px`;
    }

    return styles;
});

// 计算图标类
const iconClass = computed(() => {
    return isExpanded.value ? 'fa fa-chevron-up ml-1' : 'fa fa-chevron-down ml-1';
});

// 计算显示的文本
const displayText = computed(() => {
    return isExpanded.value || !isOverflowing.value ? props.text : props.text;
});

// 检查文本是否溢出
const checkOverflow = () => {
    if (!textRef.value) return;

    const textElement = textRef.value;
    contentHeight.value = textElement.scrollHeight;

    // 计算最大高度（行数 * 行高）
    const computedStyle = window.getComputedStyle(textElement);
    const lineHeightValue = parseFloat(computedStyle.lineHeight) || parseFloat(props.lineHeight) * 16;
    maxHeight.value = props.rows * lineHeightValue;

    isOverflowing.value = contentHeight.value > maxHeight.value;
};

// 切换展开/收起状态
const toggleExpanded = () => {
    isExpanded.value = !isExpanded.value;

    if (isExpanded.value) {
        emit('expanded');
    } else {
        emit('collapsed');
    }
};

onMounted(() => {
    nextTick(() => {
        checkOverflow();
    });
});

// 监听窗口大小变化
window.addEventListener('resize', checkOverflow);

// 组件销毁时移除事件监听
onBeforeUnmount(() => {
    window.removeEventListener('resize', checkOverflow);
});
</script>

<style scoped>
.expandable-text-container {
    position: relative;
}

.text-content {
    overflow: hidden;
    word-break: break-all;
}

.toggle-button {
    display: inline-flex;
    align-items: center;
    margin-top: 4px;
    color: #165dff;
    cursor: pointer;
    user-select: none;
    transition: color 0.2s;
}

.toggle-button:hover {
    color: #4080ff;
}

.overflow-hidden {
    position: relative;
}
</style>
